use std::collections::*;

use crate::readFileLine;

pub fn maps_new() {
    println!("===========================================");
    println!("===========================================");

    // new 创建 map
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
    println!("map scores: {:#?}.", scores);

    // 迭代器创建 map
    let teams = vec![String::from("Blue"), String::from("Yellow")];
    let initial_scores = vec![10, 50];
    println!("vec teams: {:?}.", teams);
    println!("vec initial_scores: {:?}.", initial_scores);

    // teams 作为 key， initial_scores 作为 value
    // let mut scores: HashMap<_, _> =
    let mut score_s: HashMap<String, i32> =
        teams.into_iter().zip(initial_scores.into_iter()).collect();
    println!("map score_s: {:?}.", score_s);

    owener();


    let team_name = String::from("Blue");
    let score = scores.get(&team_name);
    println!("map team_name: {:?}, score:{}.", team_name, score.unwrap());

    for (key, value) in &scores {
        println!("{}: {}", key, value);
    }

    let mut scoressss = HashMap::new();
    scoressss.insert(String::from("Blue"), 10);
    scoressss.insert(String::from("Blue"), 25);
    // 打印出 {"Blue": 25}
    println!("{:?}", scoressss);
    assert_eq!(scoressss.get(&String::from("Blue")), Some(&25));

    insert_if_not_exist();

    // 文件位于项目根目录
    // 读取一个文件中的一行数据， 并统计每个单词出现的次数
    let lineData = readFileLine("lines_for_nomarl_char.txt");

    // 代码计数:  统计一个字符串中， 每一个单词分别出现了多少次
    line_In_word_count(&lineData);
    // // 上一行不加 &lineData， 则本行会报错
    // println!("lineData: {}", lineData);
}

fn owener(){
    let field_name = String::from("Favorite color");
    let field_value = String::from("Blue");

    let mut map = HashMap::new();
    // 展示一旦键值对被插入后就为哈希 map 所拥有
    map.insert(field_name, field_value);
    // 这里 field_name 和 field_value 不再有效，
    // 尝试使用它们看看会出现什么编译错误！

    println!("map: {:?}.", map);
    // // 报错
    // println!("field_name: {:?}.", field_name);
    // println!("field_value: {:?}.", field_value);
}

// 使用 entry 方法只在键没有对应一个值时插入
fn insert_if_not_exist(){
    let mut scores = HashMap::new();

    let blueKey = String::from("Blue");
    scores.insert(blueKey, 10);
    println!("start map scores: {:#?}.", scores);

    // Entry 的 or_insert 方法在键对应的值存在时就返回这个值的可变引用，如果不存在则将参数作为新值插入并返回新值的可变引用。
    scores.entry(String::from("Red")).or_insert(26);
    println!("start map scores: {:#?}.", scores);
    assert_eq!(scores.get(&String::from("Blue")), Some(&10));
    assert_eq!(scores.get(&String::from("Red")), Some(&26));

    scores.entry(String::from("Blue")).or_insert(22);
    println!("start map scores: {:#?}.", scores);
    assert_eq!(scores.get(&String::from("Blue")), Some(&10));

}

fn line_In_word_count(lineData: &str){
    let mut map = HashMap::new();

    // 按空格拆分
    for word in lineData.split_whitespace() {
        let count = map.entry(word).or_insert(0);
        // 将这个可变引用储存在 count 变量中，所以为了赋值必须首先使用星号（*）解引用 count。
        // 这个可变引用在 for 循环的结尾离开作用域
        *count += 1;
    }

    println!("lineData： {:?}", map);
}
